#include <vector>
#include <thread>
#include <chrono>
#include "../logs/bitlog.h"

// 测试同步日志器和异步日志器的性能
void bench(const std::string& logger_name, size_t thr_count, size_t msg_count, size_t msg_len)
{
    // 1.获取日志器
    bitlog::Logger::ptr logger = bitlog::getlogger(logger_name);
    if (logger.get() == nullptr)    return ;
    std::cout << "测试日志: " << msg_count << "条, 总大小: " << (msg_count * msg_len) / 1024 << "KB\n";

    // 2.组织指定长度的日志消息
    std::string msg(msg_len - 1, 'A'); // 这里创建99个字节, 最后一个字节是换行

    // 3.创建指定数量的线程
    std::vector<std::thread> threads;  // 存放线程
    std::vector<double> cost_arry(thr_count);  // 对应线程的耗时
    size_t msg_per_thr = msg_count / thr_count;  // 总日志数量 / 线程数量 = 每个线程需要输出的日志数量
    for (int i = 0 ; i < thr_count; i++)
    {
        threads.emplace_back([&, i]() {
            // 4.线程函数内部开始计时
            auto start = std::chrono::high_resolution_clock::now();
            // 5.开始写日志
            for (int j = 0; j < msg_per_thr; j++)
                logger->fatal("%s", msg.c_str());
            // 6.线程函数内部结束技术
            auto end = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> cost = end - start;
            cost_arry[i] = cost.count();
            std::cout << "线程" << i << ": " << "\t输出日志数量: " << msg_per_thr << ", 耗时: " << cost.count() << "s\n";
        });
    }

    // 线程等待
    for (int i = 0; i < thr_count; i++)
        threads[i].join();
    
    // 7.计算总耗时: 多线程中, 每个线程都会耗费时间, 但是线程处理是并发进行的, 因此耗时最高的那个才是总耗时
    double max_cost = cost_arry[0];
    for (int i = 0; i < thr_count; i++)
        max_cost = std::max(max_cost, cost_arry[i]);
    size_t msg_per_sec = msg_count / max_cost;  // 该日志器每秒平均处理日志的数量
    size_t size_per_sec = msg_count * msg_len / (max_cost * 1024); // 该日治其平均每秒处理日志的大小

    // 8.打印输出
    std::cout << "\t总耗时: " << max_cost << "s\n";
    std::cout << "\t每秒输出日志数量: " << msg_per_sec << "条\n";
    std::cout << "\t每秒输出日志大小: " << size_per_sec << "KB\n";
}

void sync_bench()
{
    std::unique_ptr<bitlog::LoggerBuilder> builder(new bitlog::GobalLoggerBuilder());
    builder->buildLoggerName("sync_logger");
    builder->buildFormatter("%m%n");
    builder->buildLoggerType(bitlog::LoggerType::LOGGER_SYNC);
    builder->buildSink<bitlog::FileSink>("./logfile/sync.log");
    builder->build();

    bench("sync_logger", 3, 1000000, 100); // 这里第2个参数就是线程的个数,可以是单线程测试,也可以是多线程测试
}

void async_bench()
{
    std::unique_ptr<bitlog::LoggerBuilder> builder(new bitlog::GobalLoggerBuilder());
    builder->buildLoggerName("async_logger");
    builder->buildFormatter("%m%n");
    builder->buildLoggerType(bitlog::LoggerType::LOGGER_ASYNC);
    builder->buildEnableUnSafeAsync();  // 开启非安全模式  --  主要是为了将落地时间排除在外
    builder->buildSink<bitlog::FileSink>("./logfile/async.log");
    builder->build();

    bench("async_logger", 3, 1000000, 100); // 这里第2个参数就是线程的个数,可以是单线程测试,也可以是多线程测试
}

int main()
{
    // sync_bench();

    async_bench();
    return 0;
}
